import 'dart:io';

import 'package:dio/adapter.dart';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_app7/common/net/help/http_response_interceptor.dart';
import 'package:flutter_app7/common/net/help/loading_utils.dart';
import 'package:flutter_app7/common/net/mynet/error_entity.dart';
import 'package:flutter_app7/common/net/mynet/http_method.dart';
import 'package:flutter_app7/common/net/mynet/pretty_dio_logger.dart';
import 'package:flutter_app7/common/net/mynet/response_type.dart';

import 'base_entity.dart';
import 'code.dart';
import '../http_config.dart';
import '../help/data_helper.dart';

class DioManager {
  static final DioManager _shared = DioManager._internal();

  factory DioManager() => _shared;
  Dio dio;

  DioManager._internal() {
    if (dio == null) {
      BaseOptions options = BaseOptions(
        baseUrl: HttpConfig.baseApi,
        contentType: Headers.jsonContentType,
        responseType: ResponseType.json,
        receiveDataWhenStatusError: false,
        connectTimeout: 30000,
        receiveTimeout: 3000,
      );
      dio = Dio(options);
      // 配置log  输出
      dio.interceptors.add(new DioLogger());
      // 公共请求头
      dio.options.headers = DataHelper.getHeadMap();
    }
  }

  /// 请求，参数为
  /// method：请求方法，Method.POST等
  /// path：请求地址 会和base  拼接
  ///
  ///  可选配置 参数
  /// params：请求参数
  /// url  请求地址 会替换掉base  然后和  path拼接
  /// head  添加 head 头  如果key 一样 会覆盖 公共头部
  /// withLoading   是否显示 Loading
  /// responseSuccessCode  响应成功码   是否需要特别指定  没指定 就是默认配置
  /// responseType  接口请求成功 返回发   data 类型  不配置 默认按照 对象解析 , 再按照 数组解析 ,否则异常
  ///
  ///  各种回调   根据需要 选择 自己需要的回掉   responseType 会影响回调
  /// success：请求成功回调 返会对象
  /// successList,  请求成功回调 返会数组
  /// successInt, 请求成功回调 返回  int
  /// successBool,  请求成功回调    返回 bool
  /// successString, 请求成功回调    返回 字符串
  ///successNullData,  请求成功回调    无内层 date  返回
  /// successResponse  请求通了就回掉   无任何处理 需要自己处理
  /// error：请求失败回调

  Future httpRequest(Method method, String path,
      {Map<String, dynamic> params, //
      HttpResponseType responseType,
      String url,
      int responseSuccessCode,
      withLoading = true,
      Map<String, dynamic> head, //
      Function(String, Map<String, dynamic>) success,
      Function(String, List) successList,
      Function(String, int) successInt,
      Function(String, bool) successBool,
      Function(String, String) successString,
      Function(String) successNullData,
      Function(Response) successResponse,
      Function(ErrorEntity) error}) async {
    try {
      // 设置代理    只有调试模式有效
      if (kDebugMode) {
        setProxy(dio);
      }
      // 是替换掉 base url
      if (url != null) {
        dio.options.baseUrl = url;
      }

      // 添加头部
      if (head != null) {
        head.forEach((key, value) {
          dio.options.headers[key] = value;
        });
      }
      // 是否显示Loading
      if (withLoading) {
        LoadingUtils.show();
      }

      Response response;
      if (NWMethodValues[method] == "post") {
        response = await dio.request(path,
           // queryParameters: params,   // post 拼接参数 伪 post
            data:FormData.fromMap(params), // post   参数在请求体
            options: Options(method: NWMethodValues[method]));
      } else {
        response = await dio.request(path,
            queryParameters: params, // 拼接参数
            options: Options(method: NWMethodValues[method]));
      }

      // 关闭Loading
      if (withLoading) {
        LoadingUtils.dismiss();
      }
      //  200 返回成功 时候 处理  自己服务响应
      if (response != null && response.statusCode == 200) {
        // print("请求返回： "+response.toString());
        //  只要有响应  都会回掉
        if (successResponse != null) {
          successResponse(response);
        }

        //  解析返回
        BaseEntity entity = BaseEntity.fromJson(response.data);
        var successCode = Code.SUCCESS;
        if (responseSuccessCode != null) {
          successCode = responseSuccessCode;
        }

        if (entity.code == successCode) {
          print("获取数据成功：");
          // response.data[HttpConfig.data] = null;
          if (response.data[HttpConfig.data] == null) {
            if (successNullData != null) {
              successNullData(entity.message);
            }
            return;
          }
          //  按照配置类型 解析返回 如果没有配置
          //  默认按照 Object 解析  无法解析 就按照 数组解析  否则报错
          if (responseType != null) {
            // 解析 是 Object
            if (responseType == HttpResponseType.Object) {
              // print("获取数据成功： responseType: Object");
              if (success != null) {
                success(entity.message, response.data[HttpConfig.data]);
              }
            }
            // 解析 是 List
            if (responseType == HttpResponseType.List) {
              // print("获取数据成功： responseType: List");
              var list = response.data[HttpConfig.data] as List;
              if (successList != null) {
                successList(entity.message, list);
              }
            }
            // 解析 是 int
            if (responseType == HttpResponseType.Int) {
              // print("获取数据成功： responseType: List");
              int value = response.data[HttpConfig.data] as int;
              if (successInt != null) {
                successInt(entity.message, value);
              }
            }

            // 解析 是 bool
            if (responseType == HttpResponseType.Bool) {
              // print("获取数据成功： responseType: List");
              bool value = response.data[HttpConfig.data] as bool;
              if (successInt != null) {
                successBool(entity.message, value);
              }
            }
            // 解析 是 字符串
            if (responseType == HttpResponseType.String) {
              // print("获取数据成功： responseType: List");
              String value = response.data[HttpConfig.data] as String;
              if (successInt != null) {
                successString(entity.message, value);
              }
            }
          } else {
            //  是 空就默认解析
            try {
              //先当 对象解析 解析不开当数组
              success(entity.message, response.data[HttpConfig.data]);
            } catch (e) {
              // data 转换成 list 回调出去
              var list = response.data[HttpConfig.data] as List;
              if (successList != null) {
                successList(entity.message, list);
              }
            }
          }
        } else {
          // 如果被拦击器拦截住 不会响应 error
          var result = await checkCode(response.data);
          if (result != null) {
            error(ErrorEntity(
                code: entity.code,
                message: entity.message,
                response: response));
          }
        }
      } else {
        error(ErrorEntity(code: -1, message: "未知错误"));
      }
    } on DioError catch (e) {
      if (withLoading) {
        LoadingUtils.dismiss();
      }
      error(createErrorEntity(e));
    }
  }

  ///  检查 是否需要拦截
  Future<Map<String, dynamic>> checkCode(Map<String, dynamic> result) async {
    int code = result[HttpConfig.code];
    bool isCode = HttpConfig.interceptorMap.contains(code);
    if (code != null && isCode) {
      String msg = result[HttpConfig.msg];
      ResponseInterceptor.interceptorOperation(code, msg, result);
      return null;
    }
    return result;
  }

  /// 错误信息
  ErrorEntity createErrorEntity(DioError error) {
    switch (error.type) {
      case DioErrorType.CANCEL:
        {
          return ErrorEntity(code: -1, message: "请求取消");
        }
        break;
      case DioErrorType.CONNECT_TIMEOUT:
        {
          return ErrorEntity(code: -1, message: "连接超时");
        }
        break;
      case DioErrorType.SEND_TIMEOUT:
        {
          return ErrorEntity(code: -1, message: "请求超时");
        }
        break;
      case DioErrorType.RECEIVE_TIMEOUT:
        {
          return ErrorEntity(code: -1, message: "响应超时");
        }
        break;
      case DioErrorType.RESPONSE:
        {
          try {
            int errCode = error.response.statusCode;
            String errMsg = error.response.statusMessage;
            // return ErrorEntity(code: "$errCode", message: errMsg);
            switch (errCode) {
              case Code.NETWORK_ERROR_YF:
                {
                  return ErrorEntity(code: errCode, message: "请求语法错误");
                }
                break;
              case Code.NETWORK_ERROR_JJZX:
                {
                  return ErrorEntity(code: errCode, message: "服务器拒绝执行");
                }
                break;
              case Code.NETWORK_ERROR_LJ:
                {
                  return ErrorEntity(code: errCode, message: "无法连接服务器");
                }
                break;
              case Code.NETWORK_ERROR_JZ:
                {
                  return ErrorEntity(code: errCode, message: "请求方法被禁止");
                }
                break;
              case Code.NETWORK_ERROR_SE:
                {
                  return ErrorEntity(code: errCode, message: "服务器内部错误");
                }
                break;
              case Code.NETWORK_ERROR_WX:
                {
                  return ErrorEntity(code: errCode, message: "无效的请求");
                }
                break;
              case Code.NETWORK_ERROR_SXY:
                {
                  return ErrorEntity(code: errCode, message: "服务器无法响应");
                }
                break;
              case Code.NETWORK_ERROR_HTTP:
                {
                  return ErrorEntity(code: errCode, message: "不支持HTTP协议请求");
                }
                break;
              default:
                {
                  return ErrorEntity(code: errCode, message: "未知错误");
                }
            }
          } on Exception catch (_) {
            return ErrorEntity(code: Code.NETWORK_ERROR, message: "未知错误");
          }
        }
        break;
      default:
        {
          print(" 异常： code${Code.NETWORK_ERROR}    massage${error.message} ");
          return ErrorEntity(code: Code.NETWORK_ERROR, message: "网路异常,请稍后在试");
        }
    }
  }
}

///  设置代理
setProxy(dio) {
  ///不设置代理
  if (HttpConfig.Proxy == null || HttpConfig.Proxy.trim() == "") {
    return 'DIRECT';
  }
  (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
      (client) {
    client.findProxy = (url) {
      ///设置代理 电脑ip地址
      return "PROXY ${HttpConfig.Proxy}";
    };

    ///忽略证书
    client.badCertificateCallback =
        (X509Certificate cert, String host, int port) => true;
  };
}
